#pragma once

#include <stdint.h>

class DF_AuctionAlg_615 {
    /* 这个 DF_AUCTION_ALG_MAX_DIM 设置这个拍卖算法函数能够处理的
     * 统计距离矩阵的最大行数或者列数。
     */
    static const uint32_t DF_AUCTION_ALG_MAX_DIM = 512;
public:
    /* 构造函数、析构函数 */
    DF_AuctionAlg_615();
    ~DF_AuctionAlg_615();

    /* 运行拍卖算法的主要调用函数
     * 输入：
     *    inMat，统计距离矩阵
     *    thr，精门限大小
     *    inRow，统计距离矩阵的行数
     *    inCol，统计距离矩阵的列数
     * 输出：
     *    asso，记录结果的一维数组
     * 
     * 代码正确运行的条件：
     *    1. inMat 中的每个元素 >= 0
     *    2. thr 的值要大于零，代码中以 < thr 进行精门限筛选
     *    3. inRow & inCol 大于0，小于 DF_AUCTION_ALG_MAX_DIM
     *    4. asso 是一个非空的，已经定义好一维数组，其数组维度至少是 inRow 的大小
     */
    int solve(const float *inMat, float thr, uint32_t inRow, uint32_t inCol, int *asso);

    /* 设置拍卖算法中的关键参数 varepsilon
     * varepsilon 的意义类似拍卖中的一个固定的叫价增量，
     * 每一次竞拍，叫价至少要比上一家多一个 varepsilon 的数值。
     * varepsilon 的大小对拍卖算法的影响大致是：
     *     当 varepsilon 值设置较大时，拍卖算法计算快速，但是得到远离最优的结果
     *     的可能性比较高；
     *     当 设置较小值时，拍卖次数增多，运行时间稍微增多，能得到理想的匹配结果。
     *
     * ！！！注意！！！
     *     以上说明是基于拍卖算法的文献中说的，文献中一般找大的值择优，而我们是用
     *     在统计距离矩阵上，我们的目标是小的距离值。在使用中，varepsilon 一定要是
     *     负数。因此，当以绝对值理解上面的说明。
     * 
     * varepsilon 的推荐设置：
     *     varepsilon 一定要设置成负数。建议把 varepsilon 的值设置靠近 0 一些。
     *     这样得到更加精细的分配结果，时间消耗增加不多。varepsilon 的理想值大概是
     *     如果两个要比较的统计距离值相差到 varepsilon 时，不论取哪一个作为匹配，
     *     都会认为匹配结果是好的。
     *
     * 代码正确运行的条件：
     *     参数 x < 0
     */
    int setVarepsilon(float x);

private:
    /* 内部使用的结构体，表示一个分配关系对 */
    typedef struct AssoPair {
        int first;
        int second;
    } AssoPair;

    /* costMat 将用来存储统计距离矩阵中的一个值
     * row 和 col 是 costMat 的有效行数和列数
     */
    uint32_t row;
    uint32_t col;
    float costMat[DF_AUCTION_ALG_MAX_DIM][DF_AUCTION_ALG_MAX_DIM];
    /* costMat 将是输入的统计距离矩阵的一个子矩阵，
     * rowMap 记录 costMat 的第 i 行对应统计距离矩阵中的哪一行
     * colMap 记录 costMat 的第 j 列对应统计距离矩阵中的哪一列
     */
    uint16_t rowMap[DF_AUCTION_ALG_MAX_DIM];
    uint16_t colMap[DF_AUCTION_ALG_MAX_DIM];

    /* 拍卖算法中表示被拍卖物品价格的向量 */
    float price[DF_AUCTION_ALG_MAX_DIM];

    /* 记录无法找到满足精门限条件的 统计距离矩阵 中的行的数量 */
    uint32_t noMatchCount;
    /* assosCount 是关联关系计数 
     * assos 表示关联关系
     */
    uint32_t assosCount;
    AssoPair assos[DF_AUCTION_ALG_MAX_DIM];

    /* 拍卖算法中的关键叫价增量参数 */
    float varepsilon;

    /* simpleMask 是 solve() 函数中正常处理的第一步，
     * 首先过精门限，当某一行或者某一列的任意一个元素在精门限内时，
     * 这行或者列就会被标记。
     * 然后根据标记，得到 rowMap 和 colMap 的数值。并且用全部标记上的
     * 行或者列提取统计距离矩阵的子矩阵，保存在 costMat 当中。
     */
    int simpleMask(const float *inMat, float thr, uint32_t inRow, uint32_t inCol);

    /* 执行拍卖算法过程，这个 forward 函数的执行条件是 row >= col。
     * 如果不满足这个条件，算法运行时间很长，并且很可能得到差的分配结果。
     */
    int forward();

    /* 执行拍卖算法过程，这个 reverse 函数的执行条件是 row < col。
     * 如果不满足这个条件，算法运行时间很长，并且很可能得到差的分配结果。
     * forward() 和 reverse() 是互补的。
     */
    int reverse();

    /* 对应 forward() 和 reverse() 中的指派分配关系函数 */
    int assign_forward(uint32_t reportIdx, uint32_t trackIdx);
    int assign_reverse(uint32_t reportIdx, uint32_t trackIdx);
};


